apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: d8containerduplicates
  labels:
    heritage: deckhouse
    module: admission-policy-engine
    security.deckhouse.io: operation-policy
  annotations:
    metadata.gatekeeper.sh/title: "Check container duplicate parameters."
    metadata.gatekeeper.sh/version: 1.0.0
    description: >-
      Check container names and env variables for duplicates.
spec:
  crd:
    spec:
      names:
        kind: D8ContainerDuplicates
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package d8.operation_policies

        violation[{"msg": msg}] {
          container := input_containers_envs[_]
          cdata := container.envs[_]
          count(cdata) > 1
          msg := sprintf("Container <%v> in pod <%v> has duplicated env variable names: '%v'", [container.name, input.review.object.metadata.name, cdata[0]])
        }

        violation[{"msg": msg}] {
          cdata := input_containers[_]
          count(cdata) > 1
          msg := sprintf("Pod <%v> has duplicated container names: '%v'", [input.review.object.metadata.name, cdata[0]])
        }

        container_names := {name: list |
          some i
          name := input.review.object.spec.containers[i].name
          list := [obj |
            some j
            input.review.object.spec.containers[j].name == name
            obj := name
          ]
        }

        init_container_names := {name: list |
          some i
          name := input.review.object.spec.initContainers[i].name
          list := [obj |
            some j
            input.review.object.spec.initContainers[j].name == name
            obj := name
          ]
        }

        container_envs := [container |
          some i
          container_name := input.review.object.spec.containers[i].name
          envs := {name: list |
            name := input.review.object.spec.containers[i].env[_].name
            list := [obj |
              input.review.object.spec.containers[i].env[_].name == name
              obj := name
            ]
          }
          container := {"name":container_name, "envs": envs}
        ]

        init_container_envs := [container |
          some i
          container_name := input.review.object.spec.initContainers[i].name
          envs := {name: list |
            name := input.review.object.spec.initContainers[i].env[_].name
            list := [obj |
              input.review.object.spec.initContainers[i].env[_].name == name
              obj := name
            ]
          }
          container := {"name":container_name, "envs": envs}
        ]

        input_containers[c] {
          c := container_names[_]
        }

        input_containers[c] {
          c := init_container_names[_]
        }

        input_containers_envs := array.concat(container_envs, init_container_envs)
